package com.smalltao.sso.controller;

import com.smalltao.core.aop.SmalltaoLog;
import com.smalltao.core.base.controller.BaseController;
import com.smalltao.core.base.enums.ResultEnum;
import com.smalltao.core.base.result.Result;
import com.smalltao.core.utils.ToolsUtil;
import com.smalltao.sso.dto.CurrUser;
import com.smalltao.sso.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 * @author smallTao.liu
 * @version V1.0
 * @description
 * @date 2018/7/9 10:31
 */
@Controller
public class LoginController extends BaseController {

    @Value("${smalltao.sso.login-url}")
    private String loginUrl;

    @GetMapping("/login")
    @SmalltaoLog(operationType = "login:", operationName = "登录页面")
    public String login(String backUrl) {
        // 若为ajax访问 且未登录 则通过统一异常处理返回json信息
        if (isAjax()) {
            throw new AuthenticationException();
        }
        Subject subject = SecurityUtils.getSubject();
        String fallbackUrl;
        // 判断是否已登录 用户已登录 则跳回
        if (subject.isAuthenticated()) {
            fallbackUrl = getBackUrl(backUrl);
        } else {
            fallbackUrl = "/login";
        }
        return fallbackUrl;
    }

    @PostMapping(value = "/doLogin")
    public String doLogin(String userName, String userPwd, Boolean rememberMe, String backUrl, RedirectAttributes redirectAttributes) {
        if (ToolsUtil.isNull(rememberMe)) {
            rememberMe = false;
        }
        Result result = doAuthentication(userName, userPwd, rememberMe);
        String fallbackUrl;
        if (ResultEnum.OK.getCode().equals(result.getCode())) {
            fallbackUrl = getBackUrl(backUrl);
            // 当前登录用户信息
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            CurrUser currUser = new CurrUser();
            BeanUtils.copyProperties(user, currUser);
            request.getSession().setAttribute("currUser", currUser);
        } else {
            // 登录失败
            redirectAttributes.addFlashAttribute("msg", result.getMsg());
            fallbackUrl = "redirect:/login";
        }
        return fallbackUrl;
    }

    @PostMapping(value = "/login")
    @ResponseBody
    public Result login(String userName, String userPwd, Boolean rememberMe) {
        if (ToolsUtil.isNull(rememberMe)) {
            rememberMe = false;
        }
        Result result = doAuthentication(userName, userPwd, rememberMe);

        // 当前登录用户信息
        CurrUser currUser = (CurrUser) SecurityUtils.getSubject().getPrincipal();
        result.setData(currUser);
        return result;
    }

    private String getBackUrl(String backUrl) {
        String fallbackUrl = "";
        if (StringUtils.isEmpty(backUrl) || !backUrl.contains("http://")) {
            // 获取上一url 登录成功后自动跳转到上一url
            SavedRequest savedRequest = WebUtils.getSavedRequest(request);
            if (ToolsUtil.isNotNull(savedRequest)) {
                fallbackUrl = WebUtils.getSavedRequest(request).getRequestUrl();
            }
            if (StringUtils.isEmpty(fallbackUrl)) {
                if (StringUtils.isEmpty(backUrl)) {
                    fallbackUrl = "/";
                } else {
                    fallbackUrl = backUrl;
                }
            } else {
                fallbackUrl = "redirect:" + fallbackUrl.replace(serverPath, "");
            }
        } else {
            fallbackUrl = "redirect:" + backUrl;
        }
        return fallbackUrl;
    }

    private Result doAuthentication(String userName, String userPwd, boolean rememberMe) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, userPwd, rememberMe);
        Result result = new Result();
        try {
            subject.login(token);
            result.success(subject.getSession().getId(), "登录成功");
        } catch (UnknownAccountException ex) {
            result.failed(ResultEnum.BAD_REQUEST.getCode(), "帐号不存在");
        } catch (IncorrectCredentialsException ex) {
            result.failed(ResultEnum.BAD_REQUEST.getCode(), "帐号或密码错误");
        } catch (LockedAccountException ex) {
            result.failed(ResultEnum.BAD_REQUEST.getCode(), "登录失败，该用户已被冻结");
        } catch (Exception ex) {
            result.failed();
        }
        return result;
    }

    @GetMapping(value = "/unauth")
    public String unauth() {
        return "/unauth";
    }

    @GetMapping(value = "/error")
    public String error() {
        return "/error";
    }

}
